package com.jinyu.gateway.registry;

import io.netty.channel.Channel;
import io.netty.channel.ChannelId;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

@Data
@Slf4j
public class RegistryCenter {
    private static AtomicInteger registeredCount = new AtomicInteger(0);
    /**
     * 所有注册服务，名称->注册地址信息
     */
    private static ConcurrentHashMap<String, Set<ServerNode>> name2RegisteredServer = new ConcurrentHashMap<>();
    /**
     * 注册服务地址信息->已经成功连接的通道信息
     */
//    private static ConcurrentHashMap<ServerNode, Channel> registeredServer2Channel = new ConcurrentHashMap<>();

    private static ConcurrentHashMap<ChannelId, ServerNode> channelId2ServerNode = new ConcurrentHashMap<>();
    /**
     * 订阅cache，服务名称--订阅服务列表
     */
    private static ConcurrentHashMap<String, List<String>> subscribedInfo = new ConcurrentHashMap<>();

    /**
     * 保障数据操作的原子性
     *
     * @param name
     * @param address
     * @param port
     * @param channel
     */
    public static void register(String name, String address, int port, Channel channel) {
        log.info("RegistryCenter serverInfo, name:{}, address:{}, port:{}", name, address, port);
        synchronized (RegistryCenter.class) {
            ServerNode serverNode = new ServerNode(name, address, port, channel);
            Set<ServerNode> serverNodeSet = name2RegisteredServer.get(name);
            if (serverNodeSet == null) {
                serverNodeSet = new HashSet<>();
                name2RegisteredServer.put(name, serverNodeSet);
            }
            serverNodeSet.add(serverNode);
            channelId2ServerNode.put(channel.id(), serverNode);
        }
    }

    /**
     * 服务下线
     *
     * @param name
     * @param ip
     * @param port
     */
    public static void unRegister(String name, String ip, int port) {
        log.info("unRegister serverInfo, name:{}, address:{}, port:{}", name, ip, port);
        synchronized (RegistryCenter.class) {
            Set<ServerNode> serverNodeSet = name2RegisteredServer.get(name);
            if (serverNodeSet != null) {
                Optional<ServerNode> first = serverNodeSet.stream().findFirst();
                if (first.isPresent()) {
                    name2RegisteredServer.remove(first.get());
                    channelId2ServerNode.remove(first.get().getChannel().id());
                }
            }
        }
    }

    /**
     * 通过channnlId 剔除已经注册的服务
     *
     * @param channelId
     */
    public static String unRegister(ChannelId channelId) {
        synchronized (RegistryCenter.class) {
            ServerNode serverNode = channelId2ServerNode.get(channelId);
            name2RegisteredServer.remove(serverNode);
            channelId2ServerNode.remove(channelId);
            return serverNode.getName();
        }
    }

    public static Set<ServerNode> getServerNodeByName(String name) {
        return name2RegisteredServer.get(name);
    }

    public static ConcurrentHashMap<String, Set<ServerNode>> getAllRegisteredServer() {
        return name2RegisteredServer;
    }
}
